From 34d76c4844ae537c41b27ff89435f9872791da88 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 18 Dec 2017 20:12:00 -0800 Subject: [PATCH] bpf: fix integer overflows There were various issues related to the limited size of integers used in the verifier: - `off + size` overflow in __check_map_access() - `off + reg->off` overflow in check_mem_access() - `off + reg->var_off.value` overflow or 32-bit truncation of `reg->var_off.value` in check_mem_access() - 32-bit truncation in check_stack_boundary() Make sure that any integer math cannot overflow by not allowing pointer math with large values. Also reduce the scope of "scalar op scalar" tracking. Fixes: f1174f77b50c ("bpf/verifier: rework value tracking") Reported-by: Jann Horn Signed-off-by: Alexei Starovoitov Signed-off-by: Daniel Borkmann [carnil: - adjust context, we previously change verbose() signature - drop changes to include/linux/bpf_verifier.h already set ] Gbp-Pq: Topic bugfix/all Gbp-Pq: Name bpf-fix-integer-overflows.patch --- kernel/bpf/verifier.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 31bdf181470..8bd7d2e97e0 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1821,25 +1821,25 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env, s64 smin = reg->smin_value; if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) { - verbose("math between %s pointer and %lld is not allowed\n", + verbose(env, "math between %s pointer and %lld is not allowed\n", reg_type_str[type], val); return false; } if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) { - verbose("%s pointer offset %d is not allowed\n", + verbose(env, "%s pointer offset %d is not allowed\n", reg_type_str[type], reg->off); return false; } if (smin == S64_MIN) { - verbose("math between %s pointer and register with unbounded min value is not allowed\n", + verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n", reg_type_str[type]); return false; } if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) { - verbose("value %lld makes %s pointer be out of bounds\n", + verbose(env, "value %lld makes %s pointer be out of bounds\n", smin, reg_type_str[type]); return false; } -- 2.30.2